package com.lily.aidouzixun.message;

import android.os.Handler;
import android.os.Message;
import android.util.SparseArray;

/**
 * 消息调度器<br>
 * <p/>
 * 1.支持点对点的消息<br>
 * 2.支持点对面的消息广播，需事先注册<br>
 * <p/>
 */
public class MessageDispatcher {

    private static volatile MessageDispatcher instance;
    private SparseArray<Handler> handlers = null;

    private MessageDispatcher() {
        handlers = new SparseArray<Handler>();
    }

    /**
     * 获取MessageDispatcher实例，用于消息广播的发送
     *
     * @return MessageDispatcher
     */
    public static MessageDispatcher getInstance() {
        if (instance == null) {
            synchronized (MessageDispatcher.class) {
                if (instance == null) {
                    instance = new MessageDispatcher();
                }
            }
        }
        return instance;
    }

    /**
     * 消息广播注册
     *
     * @param targetHandler 接收广播的Handler
     * @param tag           标签
     */
    public void registerHandler(Handler targetHandler, int tag) {
        if (handlers != null) {
            handlers.put(tag, targetHandler);
        }
    }

    /**
     * 消息广播反注册
     *
     * @param tag 标签
     */
    public void unRegisterHandler(int tag) {
        if (handlers != null) {
            handlers.remove(tag);
        }
    }

    /**
     * 释放所有注册过的Handler,一般App退出时调用
     */
    public void releaseAll() {
        if (handlers != null) {
            handlers.clear();
            handlers = null;
        }
    }


    /************点对点消息机制****************************************************************/

    /**
     * 直接发送消息
     *
     * @param targetHandler 目标Handler
     * @param what          消息标识
     */
    public static void sendMessage(Handler targetHandler, int what) {
        try {
            if (targetHandler != null) {
                Message message = Message.obtain(targetHandler, what);
                message.sendToTarget();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 直接发送消息
     *
     * @param targetHandler 目标Handler
     * @param what          消息标识
     * @param obj           消息可附带的Object对象
     */
    public static void sendMessage(Handler targetHandler, int what, Object obj) {
        try {
            if (targetHandler != null) {
                Message message = Message.obtain(targetHandler, what, obj);
                message.sendToTarget();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 直接发送消息
     *
     * @param targetHandler 目标Handler
     * @param what          消息标识
     * @param arg1          参数1
     * @param arg2          参数2
     */
    public static void sendMessage(Handler targetHandler, int what, int arg1, int arg2) {
        try {
            if (targetHandler != null) {
                Message message = Message.obtain(targetHandler, what, arg1, arg2);
                message.sendToTarget();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 直接发送消息
     *
     * @param targetHandler 目标Handler
     * @param what          消息标识
     * @param arg1          参数1
     * @param obj         参数2
     */
    public static void sendMessage(Handler targetHandler, int what, int arg1, Object obj) {
        sendMessage(targetHandler, what, arg1, 0, obj);
    }

    /**
     * 直接发送消息
     *
     * @param targetHandler 目标Handler
     * @param what          消息标识
     * @param arg1          参数1
     * @param arg2          参数2
     * @param obj           消息可附带的Object对象
     */
    public static void sendMessage(Handler targetHandler, int what, int arg1, int arg2, Object obj) {
        try {
            if (targetHandler != null) {
                Message message = Message.obtain(targetHandler, what, arg1, arg2, obj);
                message.sendToTarget();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 延迟发送消息
     *
     * @param targetHandler 目标Handler
     * @param what          消息可附带的Object对象
     * @param delayMillis   延迟时间（毫秒）
     */
    public static void sendMessageDelayed(Handler targetHandler, int what, long delayMillis) {
        if (delayMillis <= 0) {
            sendMessage(targetHandler, what);
            return;
        }
        try {
            if (targetHandler != null) {
                Message message = Message.obtain(targetHandler, what);
                targetHandler.sendMessageDelayed(message, delayMillis);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 延迟发送消息
     *
     * @param targetHandler 目标Handler
     * @param what          消息标识
     * @param obj           消息可附带的Object对象
     * @param delayMillis   延迟时间（毫秒）
     */
    public static void sendMessageDelayed(Handler targetHandler, int what, Object obj, long delayMillis) {
        if (delayMillis <= 0) {
            sendMessage(targetHandler, what, obj);
            return;
        }
        try {
            if (targetHandler != null) {
                Message message = Message.obtain(targetHandler, what, obj);
                targetHandler.sendMessageDelayed(message, delayMillis);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /************点对面的消息广播机制*****************************************************/
    /**
     * 如果要使用消息广播，必须先注册handler，并记得反注册
     *
     * @param what 消息标识
     */
    public void sendMessage(int what) {
        try {
            if (handlers != null) {
                Message message;
                int size = handlers.size();

                for (int i = 0; i < size; i++) {
                    Handler handler = handlers.valueAt(i);
                    if (handler != null) {
                        message = Message.obtain(handler, what);
                        message.sendToTarget();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 如果要使用消息广播，必须先注册handler，并记得反注册
     *
     * @param what 消息标识
     * @param obj  消息可附带的Object对象
     */
    public void sendMessage(int what, Object obj) {
        try {
            if (handlers != null) {
                Message message;
                int size = handlers.size();

                for (int i = 0; i < size; i++) {
                    Handler handler = handlers.valueAt(i);
                    if (handler != null) {
                        message = Message.obtain(handler, what, obj);
                        message.sendToTarget();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 如果要使用消息广播，必须先注册handler，并记得反注册
     *
     * @param what 消息标识
     * @param arg1 参数1
     * @param arg2 参数2
     */
    public void sendMessage(int what, int arg1, int arg2) {
        try {
            if (handlers != null) {
                Message message;
                int size = handlers.size();

                for (int i = 0; i < size; i++) {
                    Handler handler = handlers.valueAt(i);
                    if (handler != null) {
                        message = Message.obtain(handler, what, arg1, arg2);
                        message.sendToTarget();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 如果要使用消息广播，必须先注册handler，并记得反注册
     *
     * @param what 消息标识
     * @param arg1 参数1
     * @param arg2 参数2
     * @param obj  消息可附带的Object对象
     */
    public void sendMessage(int what, int arg1, int arg2, Object obj) {
        try {
            if (handlers != null) {
                Message message;
                int size = handlers.size();

                for (int i = 0; i < size; i++) {
                    Handler handler = handlers.valueAt(i);
                    if (handler != null) {
                        message = Message.obtain(handler, what, arg1, arg2, obj);
                        message.sendToTarget();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
